# 没有使用类型提示
'''
# 'primes' is a list of integers
primes = []  # type: List[int]

# 'captain' is a string (Note: initial value is a problem)
captain = ...  # type: str


class Starship:
    # 'stats' is a class variable
    stats = {}  # type: Dict[str, int]
'''

from typing import List, ClassVar, Dict, Tuple, Optional

# int 变量，默认值为 0
num: int = 0

# bool 变量，默认值为 True
bool_var: bool = True

# 字典变量，默认为空
dict_var: Dict = {}

# 列表变量，且列表元素为 int
primes: List[int] = []


class Starship:
    # 类变量,字典类型,键-字符串,值-整型
    stats: ClassVar[Dict[str, int]] = {}

    # 实例变量，标注了是一个整型
    num: int


num = "123"
bool_var = 123
dict_var = []
primes = ["1", "2"]

print(num, bool_var, dict_var, primes)

'''
    它并不会报错，但是会有 warning，是 IDE 的智能语法提示
'''

print("==============================")

# # 正常的元组打包
a = 1, 2, 3

# 加上类型提示的元祖打包, 必须要加...  不加的话，元组打包的时候，会有一个 warning 提示
t: Tuple[int, ...] = (1, 2, 3)
print(t)

t = 1, 2, 3
print(t)

print("==============================")

# 正常元祖解包

msg = (1, 2, 3)
a, b, c = msg
print(a, b, c)

# 加上类型提示的元组解包
header: str
kind: int
body: Optional[List[str]]

# 不会warning的例子
header, kind, body = ("str", 123, ["1", '2', '3'])

# 会提示 warning 的栗子
header, kind, body = (123, 123, ["1", "2", "3"])

'''
    在类里面使用
'''


class BasicStartShip:
    captain: str = 'Prcard'  # 实例变量
    damage: int  # 实例变量，没有默认值  222
    stats: ClassVar[Dict[str, int]] = {}  # 类变量，有默认值


'''
ClassVar
是 typing 模块的一个特殊类
它向静态类型检查器指示不应在类实例上设置此变量
'''

'''
函数参数类型提示
不仅提供了函数参数列表的类型提示，也提供了函数返回的类型提示
'''


def greeting(name: str) -> str:
    return "Hello" + name


print(greeting("123"))


def greeting2(name: str, obj: Dict[str, List[int]]) -> None:
    print(name, obj)


def add(a: int, string: str, f: float, b: bool or str, l: List[str or int]) -> Tuple[List, Tuple, Dict, str or bool]:
    list1 = list(range(a))
    tup = (string, string, string)
    d = {"a": f}
    bl = b

    return list1, tup, d, bl, l


# 不会warning的调用写法
print(add(1, "2", 123, True, ["a", 1, 2, "b"]))

'''
指定类型的时候也可以用lsit set dict tuple，但是不能指定集合中的元素数据类型

List[T]、Set[T] 只能传一个类型，传多个会报错
'''

# a: List[int, str] = [1, "2"]     运行后会报错 大致意思就是：List 传了太多参数，期望 1 个，实际 2 个


d: Tuple[int, str] = (1, "2")  # 不会报错，
print(d)

d: Tuple[int] = (1, 2, 3)  # 只写一个 int，赋值两个int , IDE中元素会报 warning
print(d)

d: Tuple[int, str] = (1, "2", "2")  # 不会报错，有warning

'''
综上两个栗子，得出结论
Tuple[T] 指定一个类型的时候，仅针对同一个索引下的元素类型

如果想像 List[T] 一样，指定一个类型，可以对所有元素生效呢：  指定一个类型后，在后面加个 ... 就行
'''
d3: Tuple[int, ...] = (1, 2, 3)
d2: Tuple[Dict[str, str], ...] = ({"name": "dd"}, {"age": "18"})

